﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Compact13TaskManager
{

    public partial class frmMain : Form
    {

        bool useDLLToDoWindowEnums = true;//If false use callbacks into Managed Code with EnumWindows
        Stack<bool> timerState;

        bool showTaskbar = false;

        public frmMain()
        {
            InitializeComponent();
            timerState = new Stack<bool>();
            WindowDetail.Windows = new List<WindowDetail>();
            Interop.Init();
            if (useDLLToDoWindowEnums == true)
                menuItem15.Text = "Use Managed Code Callbacks";
            else
                menuItem15.Text = "Use Native Code (DLL) Callbacks"; ;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            PlaceCenter();

            //RefreshList();
            UpdateCount = 0;
            UpdatePeriod = 2;
            UpdateInterval = 1000;
            timer1.Interval = 1000;
            timer1.Enabled = true;
            AlwaysOnTop = true;
            AutoRefresh = true;

            Font fnt = new Font("Courier New", 10.0f, FontStyle.Regular);
            try
            {
                listBox1.Font = fnt;
            }
            catch (Exception ex)
            {
                MessageBox.Show("TaskManager prefers to use the \"Courier New\" fonts.\nPlease add \"Courier New\" font Catalog components to your OS, thx", "Compact13TaskManager");
            }
        }

        private void PlaceCenter()
        {
            int Left = (Screen.PrimaryScreen.WorkingArea.Width - this.Width) / 2;
            int Top = (Screen.PrimaryScreen.WorkingArea.Height - this.Height) / 2;
            if (Left < 0)
                Left = 0;
            if (Top < 20)
                Top = 20;
            this.Left = Left;
            this.Top = Top;
        }

        private void menuItem3_Click_1(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            Interop.DeInit();
            Application.Exit();
        }

        private void menuItem2_Click(object sender, EventArgs e)
        {
            RunNewTask();
        }

        private void RunNewTask()
        {
            timerState.Push(timer1.Enabled);
            timer1.Enabled = false;

            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            openFileDialog1.InitialDirectory = @"\Windows\";
            openFileDialog1.Filter = "All apps (*.exe)|*.exe";
            openFileDialog1.FilterIndex = 1;
            openFileDialog1.FileName = "";
            DialogResult dr = openFileDialog1.ShowDialog();

            if (dr == DialogResult.OK)
            {
                try
                {
                    string filename = openFileDialog1.FileName;
                    System.Diagnostics.Process proc = new System.Diagnostics.Process();
                    proc.EnableRaisingEvents = false;
                    proc.StartInfo.FileName = filename;
                    proc.Start();
                    PauseForm(250);
                    SetListBox1ItemIndex(-1);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not run app. Original error: " + ex.Message);
                }
            }
            else
            {
            }
            timer1.Enabled = timerState.Pop();

        }

        private void PauseForm(int time)
        {
            this.Enabled = false;
            System.Threading.Thread.Sleep(time);
            //RefreshList();
            //timer1.Enabled = AutoRefresh;
            this.Enabled = true;
            SetListBox1ItemIndex(-1);
            this.Refresh();
        }

        private void btnNewTask_Click(object sender, EventArgs e)
        {
            RunNewTask();         
        }


        private void btnEndTask_Click(object sender, EventArgs e)
        {
            timerState.Push(timer1.Enabled);
            timer1.Enabled = false;
            if (listBox1.SelectedIndex == -1)
                return;

            int itemNo = listBox1.SelectedIndex-1;
            string WindowName = WindowDetail.Windows[itemNo].WindowText;
            string WinName = WindowName;
            int consoleNum = -1;

            if (WindowName.Contains("Console"))
            {
                //Get Index back
                string numStr = WindowName.Substring("Console-".Length);
               
                try
                {
                    //Should now search for the ith Console Window
                    consoleNum = int.Parse(numStr);
                    
                }
                catch (Exception ex)
                {
                   
                }
                WinName = "Console";
            }



           
            //IntPtr hwd = Interop.FindWindowCE(null, WinName);
            IntPtr hwd = WindowDetail.Windows[itemNo].Handle;
            Interop.SetForegroundWindow(hwd);

            DialogResult dr =  MessageBox.Show("Do you want to close this app: " + WindowName + " ?");


            bool res2 = Interop.PostMessage(hwd, Interop.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
            if (!res2)
            {
                MessageBox.Show("Could close app for window " + WindowName);
            }
            else
            {
                if (WinName == "Console")
                    DeletedConsoles.Add(consoleNum);

                PauseForm(250);          
            }
            timer1.Enabled = timerState.Pop();
            return;
        }

        private void btnSwitchTo_Click(object sender, EventArgs e)
        {
            timerState.Push(timer1.Enabled);
            timer1.Enabled = false;

            if (listBox1.SelectedIndex == -1)
                return;
            int itemNo = listBox1.SelectedIndex-1;
            //string WindowName = (string)listBox1.SelectedItem;
            //IntPtr hwd = Interop.FindWindowCE(null, WindowName);
            IntPtr hwd = WindowDetail.Windows[itemNo].Handle; 
            if (hwd != IntPtr.Zero)
            {
                Interop.SetForegroundWindow(hwd);
            }
            PauseForm(250);
            timer1.Enabled = timerState.Pop();
            
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            RefreshList();
        }

        
        private void RefreshList()
        {
            //Treat timer1 as a single shot so that processing is com,plete before is starts again
            timerState.Push(timer1.Enabled);
            timer1.Enabled = false;

            //////RefreshTicks = 0;


            WindowDetail.Windows.Clear();

            ClearListBox1();
            wasConsole = false;
            long param = 137;

            if (!useDLLToDoWindowEnums)
            {
                Interop.Callback cb = new Interop.Callback(this.WndEnumProc);
                Interop.EnumWindows(cb, param);
            }
            else
            {
                //////cntr = 0;
                Interop.GetAppWindows();
                int numWindows = Interop.GetWindowCount();
                for (int i=0; i < numWindows; i++)
                {
                    StringBuilder lpWindowText = new StringBuilder(Max_String);
                    IntPtr intPtr = Interop.GetWindowDetails(lpWindowText, i);
                    string windowText = lpWindowText.ToString();
                    windowText = windowText.Replace("\0","");
                    if (windowText != "DISCARD")
                        this.WndEnumProc2(intPtr, windowText);
                }

            }
            timer1.Enabled = timerState.Pop();
        }

        //////int cntr = 0;

        //////IntPtr HANDL;
     
        //Used when DLL is used to dispaly window details
        public int WndEnumProc2(IntPtr hwnd, string windowText)
        {
            IntPtr hwndParent;
            hwndParent = Interop.GetWindowParent(hwnd);
            if (hwndParent != (IntPtr)0)
                return 137;

            //if ((uint)hwnd == 0xFE160002)
                //return 130;





            //////cntr++;
            ////if (cntr == 1)
            ////    HANDL = hwnd;
            ////if (cntr > 4)
            ////    return 129;

            ////StringBuilder lpWindowText = new StringBuilder((int)Max_String);

            ////Interop.GetWindowText(HANDL, lpWindowText, Max_String);

            ////int len = Interop.GetWindowTextLength(hwnd);
            ////if (len == 0)
            ////    return 137;

            ////windowText = lpWindowText.ToString();
            ////windowText = windowText.Replace("\0", "");

            //if (windowText.Length < 2)
            //    return 137;
            //else if (windowText == "")
            //    return 137;
            //else if (!IsAlphaNumeric(windowText))
            //    return 137;
            //else if (windowText.Contains("About Windows Embedded Compact 2013"))
            //    return 137;
            //else if (windowText == "TaskBar")
            //    return 137;
            //else if (windowText == "Desktop")
            //    return 137;
            //else if (windowText.Contains( "Default Ime"))
            //    return 137;


            //if (windowText == "Console")
            //{
            //    if (wasConsole)
            //    {
            //        wasConsole = false;
            //        return 137;
            //    }

            //    ConsoleCount++;
            //    while (DeletedConsoles.Contains(ConsoleCount))
            //        ConsoleCount++;
            //    windowText += "-" + ConsoleCount.ToString();
            //    wasConsole = true;
            //}
            //else
            //    wasConsole = false;



            //windowText = "Window";
            WindowDetail winDetail = new WindowDetail( hwnd, windowText);
            WindowDetail.Windows.Add(winDetail);

            uint hwnd_hex = (uint)hwnd;
            if (windowText.Length > WindowDetail.WindowTextLength)
                windowText = windowText.Substring(0, WindowDetail.WindowTextLength);
            AddListBox1Item(string.Format(" {0,-" + WindowDetail.WindowTextLength.ToString() + "}  0x{1,-8:x}", windowText, hwnd_hex));
            if (listBox1.Items.Count == (WindowListCurrentIndex + 1))
                SetListBox1ItemIndex(WindowListCurrentIndex);
            //////RefreshTicks = 0;
            
            return 137;
        }

        public int WndEnumProc(IntPtr hwnd, long lParam)
        {
            //////RefreshTicks = 0;

            //Check if top level winow of app.
            IntPtr hwndParent;
            hwndParent = Interop.GetWindowParent(hwnd);
            if (hwndParent != (IntPtr)0)
                return 137;

            int maxText = 256;
            StringBuilder lpWindowText = new StringBuilder((int)maxText);

            Interop.GetWindowText(hwnd, lpWindowText, maxText);


            string windowText = lpWindowText.ToString();
            if (windowText.Length < 2)
                return 137;
            else if (windowText == "")
                return 137;
            else if (!IsAlphaNumeric(windowText))
                return 137;
            else if (windowText.Contains("About Windows Embedded Compact 2013"))
                return 137;
            else if (windowText == "TaskBar")
                return 137;
            else if (windowText == "Desktop")
                return 137;


            //if (windowText == "Console")
            //{
            //    if (wasConsole)
            //    {
            //        wasConsole = false;
            //        return 137;
            //    }

            //    ConsoleCount++;
            //    while (DeletedConsoles.Contains(ConsoleCount))
            //        ConsoleCount++;
            //    windowText += "-" + ConsoleCount.ToString();
            //    wasConsole = true;
            //}
            //else
            //    wasConsole = false;

            WindowDetail winDetail = new WindowDetail(hwnd, windowText);
            WindowDetail.Windows.Add(winDetail);
 
            uint xx = (uint) hwnd;
            if (windowText.Length > WindowDetail.WindowTextLength)
                windowText = windowText.Substring(0, WindowDetail.WindowTextLength);
            AddListBox1Item(string.Format(" {0,-" + WindowDetail.WindowTextLength.ToString() + "}  0x{1,-8:x}", windowText, xx));
            if (listBox1.Items.Count == (WindowListCurrentIndex + 1))
                SetListBox1ItemIndex( WindowListCurrentIndex);
            //////RefreshTicks = 0;
            return 137;
        }

        public void HideStartBar()
        {
            IntPtr handle;

            try
            {
                // Find the handle to the Start Bar
                handle = Interop.FindWindowCE("HHTaskBar", null);

                // If the handle is found then hide the start bar
                if (handle != IntPtr.Zero)
                {
                    // Hide the start bar
                    Interop.SetWindowPos(handle, IntPtr.Zero, 0, 0, 0, 0, Interop.SWP_HIDEWINDOW);
                }
            }
            catch
            {
                MessageBox.Show("Could not hide Start Bar.");
            }
        }

        public void ShowStartBar()
        {
            IntPtr handle;

            try
            {
                // Find the handle to the Start Bar
                handle = Interop.FindWindowCE("HHTaskBar", null);

                // If the handle is found then show the start bar
                if (handle != IntPtr.Zero)
                {

                   int TaskbarX = 0;
                   int TaskbarWidth = Screen.PrimaryScreen.Bounds.Width;
                   int TaskbarHeight = 26;
                   int TaskbarY = 1+ Screen.PrimaryScreen.Bounds.Height - TaskbarHeight;//Bottom left corner of taskbar
                    // Show the start bar
                    Interop.SetWindowPos(handle, IntPtr.Zero, TaskbarX, TaskbarY, TaskbarWidth, TaskbarHeight, Interop.SWP_SHOWWINDOW);
                }
            }
            catch
            {
                MessageBox.Show("Could not show Start Bar.");
            }
        }



        //Timer interval is fixed at 1000ms = UpdateInterval.
        //Change update rate by changing UpdateCount = 1,2,5
        //Ignore updates if AutoRefresh is false
        private void timer1_Tick(object sender, EventArgs e)
        {
            RefreshList();

            if (AlwaysOnTop)
                this.BringToFront();
            return;
            /////////////
            ////////////if (InRefresh)
            ////////////{
            ////////////    if (RefreshTicks++ == MaxRefreshTticks)
            ////////////    {
            ////////////        InRefresh = false;
            ////////////        UpdateCount = 0;
            ////////////    }
            ////////////}

            ////////////if ((AutoRefresh) && (!InRefresh))
            ////////////{

            ////////////        if (++UpdateCount == UpdatePeriod)
            ////////////        {
            ////////////            UpdateInterval = 0;
            ////////////            RefreshList();
            ////////////        }
            ////////////}

            ////////////if (AlwaysOnTop)
            ////////////    this.BringToFront();
        }
        
        /// <summary>
        /// Set AlwaysOnTop property
        /// </summary>
        private void menuItem5_Click(object sender, EventArgs e)
        {
            AlwaysOnTop = !AlwaysOnTop;
            menuItem5.Checked = AlwaysOnTop;
        }

        private void menuUpdateSpeedSubMenuItems_Click(object sender, EventArgs e)
        {
            timerState.Push(timer1.Enabled);
            timer1.Enabled = false;
            menuItem9.Checked = false;
            menuItem10.Checked = false;
            menuItem11.Checked = false;
            menuItem12.Checked = false;

            MenuItem menIt = (MenuItem)sender;
            menIt.Checked  = true;

            switch (menIt.Text)
            {
                case "High":
                    UpdatePeriod = 1;
                    AutoRefresh = true;
                    break;
                case "Medium":
                    UpdatePeriod = 2;
                    AutoRefresh = true;
                    break;
                case  "Low":
                    UpdatePeriod = 5;
                    AutoRefresh = true;
                    break;
                case "Stop":
                    AutoRefresh = false;
                    break;

            }
            timer1.Enabled = timerState.Pop();


        }

        /// <summary>
        /// Record the current list index
        /// </summary>
        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
         {
             int index = listBox1.SelectedIndex;
             if ((index != -1) && (index !=0) )
                WindowListCurrentIndex = index;
             if (index == 0)
             {
                 listBox1.SelectedIndex = WindowListCurrentIndex;
                 index = WindowListCurrentIndex;
             }
             return;
         }

        /// <summary>
        /// Activate currently selected app.
        /// </summary>
        private void listBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            char ch = e.KeyChar;
            if (ch == '\r')
                btnSwitchTo_Click(null, null);
        }

        private void menuItem14_Click(object sender, EventArgs e)
        {
            timerState.Push(timer1.Enabled);
            timer1.Enabled = false;
            this.Hide();
            
           // MessageBox.Show("This project is a simple C# implementation of a\nTask Manager for Compact 2013.\n\nBrought to you by David Jones.\nSee my other Windows Embedded Compact/CE projects on Codeplex.\n\nEnjoy!", "Compact13TaskManager"); 
           AboutBox.ShowAsDialog();
           this.Show();
           this.BringToFront();
           timer1.Enabled = timerState.Pop();
          
        }



        private void menuItem15_Click(object sender, EventArgs e)
        {
            timerState.Push(timer1.Enabled);
            timer1.Enabled = false;

            //Toggle
            useDLLToDoWindowEnums = !useDLLToDoWindowEnums;
            if (useDLLToDoWindowEnums == true)
            {
                menuItem15.Text = "Use Managed Code Callbacks";
            }
            else
            {
                menuItem15.Text = "Use Native Code (DLL) Callbacks";
            }
            

            timer1.Enabled= timerState.Pop();
        }

        private void menuItem16_Click(object sender, EventArgs e)
        {
            //showTaskbar

            

            showTaskbar = !showTaskbar;
            if (showTaskbar == true)
            {
                menuItem16.Text = "Hide Taskbar";
                ShowStartBar();
            }
            else
            {
                menuItem16.Text = "Show Taskbar";
                HideStartBar();
            }
        }



        
}
    
}
